package com.donger.common.pay.handler;

import cn.hutool.json.JSONUtil;
import com.donger.common.core.exception.BizException;
import com.donger.common.pay.config.WxBeanProperties;
import com.ijpay.core.enums.SignType;
import com.ijpay.core.enums.TradeType;
import com.ijpay.core.kit.WxPayKit;
import com.ijpay.wxpay.WxPayApi;
import com.ijpay.wxpay.WxPayApiConfig;
import com.ijpay.wxpay.WxPayApiConfigKit;
import com.ijpay.wxpay.model.RefundModel;
import com.ijpay.wxpay.model.UnifiedOrderModel;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
@Slf4j
@RequiredArgsConstructor
public class WxPayhandler implements PayHandler {

    private final WxBeanProperties wxBeanProperties;

    @Override
    public Map<String, String> UnifiedOrder(String openId, String body, String attach, Integer fee, String outTradeNo) {
        if (openId == null) {
            throw new BizException("OPENID不能为空");
        }

//        java.lang.String ip = IpKit.getRealIp(request);
        WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig();

        Map<java.lang.String, java.lang.String> params = UnifiedOrderModel
                .builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                // 随机串
                .nonce_str(WxPayKit.generateStr())
                // 商品描述
                .body(body)
                .attach(attach)
                // 订单号，商户下唯一
                .out_trade_no(outTradeNo)
                .total_fee(java.lang.String.valueOf(fee))
                .spbill_create_ip("")
                .notify_url(wxBeanProperties.getNotifyUrl())
                .trade_type(TradeType.JSAPI.getTradeType())
                .openid(openId)
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5);

        log.debug("统一支付参数构建 -> {}", params);

        // 发送请求
        java.lang.String xmlResult = WxPayApi.pushOrder(false, params);

        log.debug("统一支付构造结果 ->{}", xmlResult);
        // 将请求返回的 xml 数据转为 Map，方便后面逻辑获取数据
        Map<java.lang.String, java.lang.String> resultMap = WxPayKit.xmlToMap(xmlResult);
        // 判断返回的结果
        java.lang.String returnCode = resultMap.get("return_code");
        java.lang.String returnMsg = resultMap.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            throw new BizException(returnMsg);
        }
        java.lang.String resultCode = resultMap.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            throw new BizException(returnMsg);
        }

        // 以下字段在 return_code 和 result_code 都为 SUCCESS 的时候有返回

        java.lang.String prepayId = resultMap.get("prepay_id");
        // 二次签名，构建公众号唤起支付的参数,这里的签名方式要与上面统一下单请求签名方式保持一致
        Map<java.lang.String, java.lang.String> packageParams = WxPayKit.prepayIdCreateSign(prepayId, wxPayApiConfig.getAppId(),
                wxPayApiConfig.getPartnerKey(), SignType.MD5);
        // 将二次签名构建的数据返回给前端并唤起公众号支付
        java.lang.String jsonStr = JSONUtil.parseObj(packageParams).toString();


        log.debug("数据加密 -> {}", jsonStr);

        return packageParams;
    }

    @Override
    public Map<String, String> queryOrder(String transactionId, String outTradeNo) {
        return null;
    }

    @Override
    public Map<String, String> refund(String transactionId, String outTradeNo, Integer refundFee, Integer totalFee, String outRefundNo) {
        WxPayApiConfig wxPayApiConfig = WxPayApiConfigKit.getWxPayApiConfig();
        Map<String, String> params = RefundModel.builder()
                .appid(wxPayApiConfig.getAppId())
                .mch_id(wxPayApiConfig.getMchId())
                .nonce_str(WxPayKit.generateStr())
                .transaction_id(transactionId)
                .out_trade_no(outTradeNo)
                .out_refund_no(outRefundNo)
//                .total_fee(fee)
//                .refund_fee(fee)
                .total_fee(String.valueOf(totalFee))
                .refund_fee(String.valueOf(refundFee))
                .notify_url(wxBeanProperties.getRefundNotifyUrl())
                .build()
                .createSign(wxPayApiConfig.getPartnerKey(), SignType.MD5);
        String refundStr = WxPayApi.orderRefund(false, params, wxPayApiConfig.getCertPath(), wxPayApiConfig.getMchId());
        log.info("refundStr: {}", refundStr);
        Map<String, String> stringStringMap = WxPayKit.xmlToMap(refundStr);
        String returnCode = stringStringMap.get("return_code");
        String returnMsg = stringStringMap.get("return_msg");
        if (!WxPayKit.codeIsOk(returnCode)) {
            throw new BizException(returnMsg);
        }
        String resultCode = stringStringMap.get("result_code");
        if (!WxPayKit.codeIsOk(resultCode)) {
            String errCodeDes = stringStringMap.get("err_code_des");
            throw new BizException(errCodeDes);
        }
        return new HashMap<>();
    }
}
